import gobject
import Exceptions
import Sysaccess
import os


DEFAULT_DISPLAY_TEXT = {
    'ddl param' : {    
        'public' : 'public ip',
        'local'  : 'local ip',
        'dns'    : 'dns',
    },
    'ddl protocol' : {
        'SAMBA'  : 'Samba',
        'SSH'    : 'Ssh',
        'FTP'    : 'Ftp',
        'NFS'    : 'Nfs',
    },
}

DEFAULT_GLOBAL_CONFIG = {
    'VERSION'  : (0,0,8),
    'DEBUG'    : False,
    'MAIN WINDOW WIDTH'  : 600,                 
    'MAIN WINDOW HEIGHT' : 650,
    'PROTOCOLS' : ['SAMBA','SSH','FTP','NFS'],
    'PORT' : { 
        'SSH'   : 22,
        'FTP'   : 21,
        'SAMBA' : 139,
        'NFS'   : 2049,
    },
}

DEFAULT_USER_CONFIG = {
    'DEFAULT MOUNT POINT' : '/mnt/miam/',
    'TIMERS' : {
        'LATENCY'       : 10, #10sec
        'LOCATION'      : 10, #10min <--- useless 
        'NETWORK STATE' : 1, #1sec
        'MTAB'          : 10, #10sec
        'AUTOMOUNT'     : 1, #1sec
    },
    'START HIDE'    : False,
    'STARTUP START' : False,
    'NEVER SHOW DIALOG' : set(),
    'UMOUNT ON EXIT' : False,
    'MAIN WINDOW POS' : None,
    'MAIN WINDOW SIZE' : None,
}

DEFAULT_NETWORK_STATE = {
    'STATE' : None,
    'INTERFACE' : None,
    'LOCAL ADDR' : None,
    'NETMASK' : None,
    'GATEWAY' : None,
    'PUBLIC ADDR' : None,
    'CURRENT LOCATION' : None,
} 

REGEX = {
      'REGEX_IP' : '^([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])$',
      'REGEX_DOMAIN' : '^([a-zA-Z0-9_\-]+(\.[a-zA-Z0-9_\-]+)*)?$',
      'REGEX_MOUNT_POINT' : '^/\S+(/\S+)*$',
      'REGEX_PATH' : '^\S+(/\S+)*$',
      'REGEX_LOGIN' : '^\S+$',
      'REGEX_PASSWORD' : '^\S+$',
      'REGEX_NAME' : '^.+$',
      'REGEX_PORT' : '^\d{0,5}$'
      }
        
class Config(gobject.GObject):
    '''This class is only a container for all config dict we need'''
    __gsignals__ = {
        # set detailed signal (set::DICT::ITEM) is emit when a config dict item is set
        # callback has to look like  : def callback(config, new_value, old_value)
        'set' : (gobject.SIGNAL_DETAILED, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT))
    }
    
    def __init__(self,user_home_path):
        '''construcor'''
        gobject.GObject.__init__(self)
        if user_home_path == False:
             DEFAULT_PATH_CONFIG = {
                'LOCATION PICKLE'       : './pickles/locations.pkl',
                'SHARE PICKLE'          : './pickles/shares.pkl',
                'ID PICKLE'             : './pickles/id.pkl',
                'CONFIG USER PICKLE'    : './pickles/user_conf.pkl',
                'IMAGES'                : './images/',
                'SSH ROOT HOST KEY FILE': '/root/.ssh/known_hosts'
            }
        else:
             DEFAULT_PATH_CONFIG = {
                'LOCATION PICKLE'       : user_home_path + '/.miam/pickles/locations.pkl',
                'SHARE PICKLE'          : user_home_path + '/.miam/pickles/shares.pkl',
                'ID PICKLE'             : user_home_path + '/.miam/pickles/id.pkl',
                'CONFIG USER PICKLE'    : user_home_path + '/.miam/pickles/user_conf.pkl',
                'IMAGES'                : './images/',
                'SSH ROOT HOST KEY FILE': user_home_path + '/.ssh/known_hosts'
            }
#        for key in DEFAULT_PATH_CONFIG:
#            print key+" "+DEFAULT_PATH_CONFIG[key]
        self.path = ConfigDict(self,'PATH',DEFAULT_PATH_CONFIG)             # store all the path relative config values <-- has to be saved ?
        self.display_text = ConfigDict(self,'DISPLAY TEXT',DEFAULT_DISPLAY_TEXT)
        self.regex = ConfigDict(self,'REGEX',REGEX)
        self.network = ConfigDict(self,'NETWORK',DEFAULT_NETWORK_STATE)     # store the newtwork relative config values
        self.glob = ConfigDict(self,'GLOBAL', DEFAULT_GLOBAL_CONFIG)        # store the global config values
        self.user = ConfigDict(self,'USER', DEFAULT_USER_CONFIG, self.path['CONFIG USER PICKLE'])   # save the user relative config values
        
class ConfigDict(dict):
    '''dict with signals and autosave'''
    
    def __init__(self, config, name, defaults, path = None):
        '''constructor'''
        self.name = name
        self.config = config        #only to emit signal
        self.defaults = defaults    #the default config dict
        self.path = path            #the path to save the dict or None
        self.store = None           #the heart of this custom dict
        self.load()
    
    def load(self):
        '''try to load the dict or fallback to default'''
        self.load_defaults()
        if self.path:
            load = Sysaccess.load(self.path)
            if load:
                for key,item in self.store.iteritems():
                    if key in load.iterkeys():
                        # load array
                        # I have to write a recursive code here but didn't had time yet.
                        if isinstance(self.store[key],dict):
                            for dict_key,dict_value in self.store[key].iteritems():
                                if dict_key in load[key].iterkeys():
                                    self.store[key][dict_key] = load[key][dict_key] 
                        else:
                            self.store[key] = load[key]
            else:
                self.load_defaults()
        self.save()
    
    def load_defaults(self):
        self.store = self.defaults.copy()
    
    def save(self):
        '''try to save the dict'''
        if self.path:
            Sysaccess.save(self.store,self.path)
         
    def __getitem__(self,item):
        """ return item or raise error"""
        if item in self.store :
            return self.store[item]
        else:
            if item in self.defaults:
                print "plop"
                tmp = self.store.copy()
                self.load_defaults()
                for key,value in tmp.iteritems():
                    if key in self.store:
                        self.store[key] = value
                    else:
                        print 'key %s has been removed from %s' % (key,self.name)
                return self.store[item]
            else:
                raise Exceptions.ConfigAttributeError(self,item)
            
    def __setitem__(self, item, value):
        '''set value, emit signal and save config dict ( only on value change )'''
        if item in self.store : # field has to be define in the default dict
            old_value = self.store[item]
            if value != old_value:
                print self.name + " : " + item + "( " + str(old_value) + " --> " + str(value) + " )" 
                self.store[item] = value
                self.config.emit('set::'+self.name+'::'+item,value,old_value)
                self.save()
        else:
            if item in self.defaults:
                tmp = self.store.copy()
                self.load_defaults()
                for key,value in tmp.iteritems():
                    if key in self.store:
                        self.store[key] = value
                    else:
                        print 'key %s has been removed from %s' % (key,self.name)
                self[item] = value
            else:
                raise Exceptions.ConfigAttributeError(self,item)
    
    def __iter__(self):
        '''custom dict iterator'''
        return self.store.iteritems()
    
    def __repr__(self):
        '''repr override'''
        return self.store.__repr__()
